use std::{path::Path, process::Command, usize};

/*
Check PID exists
*/
pub fn pid_exists(pid: usize) -> bool {
    if cfg!(target_os = "windows") {
        // tasklist /FI "PID eq {}"
        match Command::new("tasklist")
            .args(&["/FI", &format!("PID eq {pid}")])
            .output()
        {
            Ok(output) => {
                // println!("{:?}", cmd::decode(&output.stdout, 0));
                // stdout contains = ?
                // ========================= ======== ================ =========== ============
                return output.status.success() && output.stdout.contains(&61);
            }
            Err(e) => {
                panic!("{e}")
            }
        }
    } else if cfg!(target_os = "macos") {
        match Command::new("ps").arg("-p").arg(&format!("{pid}")).output() {
            Ok(output) => return output.status.success(),
            Err(e) => {
                panic!("{e}");
            }
        }
    } else {
        // Unix Or Linux
        Path::new(&format!("/proc/{pid}")).exists()
    }
}

/*
Kill PID
*/
pub fn kill(pid: usize, force: bool) -> bool {
    if cfg!(target_os = "windows") {
        // taskkill /PID 20564 /F
        // taskkill /PID 2072
        let mut cmd = Command::new("taskkill");
        cmd.arg("/PID").arg(&format!("{pid}"));
        if force {
            cmd.arg("/F");
        }

        match cmd.output() {
            Ok(output) => {
                return output.status.success()
            }
            Err(e) => {
                panic!("{e}")
            }
        }
    } else {
        let mut cmd = Command::new("kill");
        if force {
            cmd.arg("-9");
        }
        cmd.arg(&format!("{pid}"));
        match cmd.output() {
            Ok(output) => return output.status.success(),
            Err(e) => {
                panic!("{e}");
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::ps::kill;

    use super::pid_exists;

    #[test]
    fn test1() {
        let run = pid_exists(2072);
        assert_eq!(run, true)
    }

    #[test]
    fn test_kill() {
        let run = kill(22800, false);
        assert_eq!(run, true);
        // let run = kill(22800, true);
        // assert_eq!(run, true);
    }
}
